/*******************************************************************************
 * Copyright (c) 2011 Grupo de Sistemas Inteligentes (GSI) - DIT UPM
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package es.upm.dit.gsi.eclipse.jadex.adfmanager.wizards;

import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWizard;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.operation.*;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.core.runtime.CoreException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import es.upm.dit.gsi.eclipse.jadex.navigator.SubChild;
import es.upm.dit.gsi.eclipse.jadex.util.ImageFactory;

/**
 * Wizard for adding new imports to the selected agent
 * 
 * It has got one page:
 *  - Page1: List of imports with the ability to Add/Modify/Delete
 *  
 * @author Mario Moreno Zarco
 */

public class AddImportWizard extends Wizard implements INewWizard {
	private AddImportWizardPage1 page1;
	private ISelection selection;
	

	/**
	 * Constructor for AddImportWizard
	 */
	public AddImportWizard(ISelection selection) {
		super();
		setNeedsProgressMonitor(true);
		this.selection = selection;
		setDefaultPageImageDescriptor(ImageFactory.getImageDescriptor(ImageFactory.GSI_BANNER_SMALL));
	}
	
	/**
	 * Adding pages to the wizard.
	 */
	public void addPages() {
		ArrayList<String> importsList = XMLparser();
		page1 = new AddImportWizardPage1(selection, importsList);
		page1.setTitle("Add Import/set Wizard");
		addPage(page1);
		
	}

	/**
	 * This method is called when 'Finish' button is pressed in
	 * the wizard. We will create an operation and run it
	 * using wizard as execution context.
	 */
	public boolean performFinish() {
		final IFile agentFile = (IFile)((IStructuredSelection)selection).getFirstElement();
		
		//This gets the new imports from the input table in page1
		final ArrayList<String> importsList = AddImportWizardPage1.getImportsList();
				
		IRunnableWithProgress op = new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor) throws InvocationTargetException {
				try {
					doFinish(agentFile, importsList, monitor);
				} catch (CoreException e) {
					throw new InvocationTargetException(e);
				} finally {
					monitor.done();
				}
			}
		};
		
		try {
			getContainer().run(true, false, op);
		} catch (InterruptedException e) {
			return false;
		} catch (InvocationTargetException e) {
			Throwable realException = e.getTargetException();
			MessageDialog.openError(getShell(), "Error", realException.getMessage());
			return false;
		}
		return true;
	}
	
	/**
	 * The worker method. It will add the necessary information to the ADF file in 
	 * order to configure the new imports.
	 */
	private void doFinish(
			IFile agentFile,
			ArrayList<String> importsList,
			IProgressMonitor monitor)
		throws CoreException {
		
		monitor.beginTask("Modificating ADF File", 2);
		
		try{
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
		Document doc = docBuilder.parse(agentFile.getRawLocation().toOSString());
	 
		//Get the old <imports> node 
		Node imports = doc.getElementsByTagName("imports").item(0);		
		
		//Creates a new <imports> node
		Element newImportsNode = doc.createElement("imports");
		
		//Writes into the newImportsNode the imports written in the importsTable
		for (String import1 : importsList){
			Element newImport = doc.createElement("import");
			newImport.setTextContent(import1);
			newImportsNode.appendChild (newImport);
		}
		
		//Replaces the old imports node with the new node newImportsNode
		imports.getParentNode().replaceChild(newImportsNode, imports);
		
		//Writes the content into the XML file
		Auxiliary.writeToXML(doc, agentFile, monitor);

		}
		catch(Exception e1){
			e1.printStackTrace();
		}
	    System.out.println("Done");
	    monitor.worked(1);
	}
		
	/**
	 *  Extracts the content of the imports associated to the imports label in the XML file and 
	 *  puts them into an ArrayList<String>
	 */
	
	private ArrayList<String> XMLparser(){
		ArrayList<String> importsList = new ArrayList<String>();
		
		IFile agentFile = (IFile)((IStructuredSelection)selection).getFirstElement();
		
		try{
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance ( );
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(agentFile.getRawLocationURI().getRawPath());
		NodeList imports = document.getElementsByTagName("import");
		
		for (int i = 0; i < imports.getLength(); i++){
			importsList.add(imports.item(i).getTextContent());
			
		}
		}catch(Exception e1){
			return new ArrayList<String>();
		}
		
		return importsList;
		
	}

	/**
	 * We will accept the selection in the workbench to see if
	 * we can initialize from it.
	 * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
	 */
	public void init(IWorkbench workbench, IStructuredSelection selection) {
		this.selection = selection;
	}
}